﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CommonClasses
{   
    public class PokerHand : Hand
    {
        private Dictionary<int, int> dup_cards; // = new Dictionary<int, int>();
        private List<int> all_cards_fv = new List<int>();
        private List<string> all_cards_suits = new List<string>();
        private int[] unique_cards_fv;
        private string[] unique_cards_suits;
        private List<int> desc_ordered_cards_fv = new List<int>();

        public new List<int> Total = new List<int>();
        public string name;

        public new int MaxCards = 5;

        private void _analyze_for_sets()
        {
            all_cards_fv = new List<int>();
            all_cards_suits = new List<string>();
           
            // Breakdown the CardsOnHand property.
            foreach (Card c in CardsOnHand)
            {
                all_cards_fv.Add(c.FaceValue);
                all_cards_suits.Add(c.Suit);
            }

            // Create a set of unique faceValue and suits from cards_fv and cards_suits.
            var Hash_fv = new HashSet<int>(all_cards_fv);
            var Hash_suits = new HashSet<string>(all_cards_suits);

            // Convert from var type to int[] and string[] type respectively.
            unique_cards_fv = Hash_fv.ToArray();
            unique_cards_suits = Hash_suits.ToArray();
        }

        private void _analyze_for_duplicates()
        {
            dup_cards = new Dictionary<int, int>();

            if (unique_cards_fv != null && all_cards_fv != null)
            {
                foreach (int uc in unique_cards_fv)
                {
                    int dup_counter = 0;
                    foreach (int c in all_cards_fv)
                    {
                        if (c == uc)
                        {
                            dup_counter++;
                        }
                    }
                    dup_cards.Add(uc, dup_counter);
                }
            }            
        }

        private void _sort_cards()
        {
            desc_ordered_cards_fv = all_cards_fv.ToList<int>();
            desc_ordered_cards_fv.Sort();
            desc_ordered_cards_fv.Reverse();
        }        

        private bool isRoyalFlush()
        {
            if (isStraightFlush() && desc_ordered_cards_fv[0] == 14)  // 14 is the face value for Ace.
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        private bool isStraightFlush()
        {       
            if (isStraight() && isFlush())
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        private bool isFourKind()
        {
            if (unique_cards_fv.Length == 2)
            {
                bool is_4_kind = false;
                foreach (KeyValuePair<int, int> pair in dup_cards)
                {
                    if (pair.Value == 4)
                    {
                        is_4_kind = true;
                        break;
                    }
                }

                if (is_4_kind)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else
            {
                return false;
            }
        }

        private bool isFullHouse()
        {
            if (isThreeKind() && isPair())
            {
                return true;
            }
            else
            {
                return false;
            }
            
        }

        private bool isFlush()
        {
            // It is a flush if there is only 1 item in card_set.
            if (unique_cards_suits.Length == 1)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        private bool isStraight()
        {
            int last_index = unique_cards_fv.Length - 1;

            // Example: all_card_fv = (4, 5, 6, 7, 8)
            // MaxValue - MinValue + 1 ==> (8 - 4 + 1) = 5
            // compare 5 to CardsOnHand which should be 5 AND compare length of unique_cards_fv to length of CardsOnHand.
            if ((desc_ordered_cards_fv[0] - desc_ordered_cards_fv[last_index] + 1) == CardsOnHand.Count() 
                && unique_cards_fv.Length == CardsOnHand.Count())
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        private bool isThreeKind()
        {          
            if (unique_cards_fv.Length >= 2)
            {
                bool is_3_kind = false;       
                foreach (KeyValuePair<int, int> pair in dup_cards)
                {
                    if (pair.Value == 3)
                    {
                        is_3_kind = true;
                        break;
                    }
                }

                if (is_3_kind)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else
            {
                return false;
            }
        }

        private bool isTwoPair()
        {            
            if (unique_cards_fv.Length == 3)
            {
                bool is_2_pair = false;
                int num_pair = 0;
                foreach (KeyValuePair<int, int> pair in dup_cards)
                {
                    if (pair.Value == 2)
                    {
                        num_pair++;
                    }
                    if (num_pair == 2)
                    {
                        is_2_pair = true;
                        break;
                    }
                }                

                if (is_2_pair)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else
            {
                return false;
            }
        }

        private bool isPair()
        {
            if (unique_cards_fv.Length >= 2)
            {
                bool is_pair = false;
                int num_pair = 0;
                foreach (KeyValuePair<int, int> pair in dup_cards)
                {
                    if (pair.Value == 2)
                    {
                        num_pair++;                        
                    }
                    if (num_pair == 1)
                    {
                        is_pair = true;
                        break;
                    }
                }

                if (is_pair)
                {                    
                    return true;
                }
                else
                {                    
                    return false;
                }
            }
            else
            {
                return false;
            }
        }

        private bool isHighCard()
        {
            if (unique_cards_fv.Length == MaxCards && !(isFlush()) && !(isStraight()))
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        public override void calculate_total()
        {
            if (CardsOnHand.Count == MaxCards)
            {
                _analyze_for_sets();
                _analyze_for_duplicates();
                _sort_cards();

                # region pokerhands
                //if (isHighCard())
                //{
                //    Total.Clear();
                //    Total.Add(1);

                //    for (int i = 0; i < desc_ordered_cards_fv.Count; i++)
                //    {
                //        Total.Add(desc_ordered_cards_fv[i]);
                //    }
                //}
                //else if (isPair())
                //{
                //    Total.Clear();
                //    Total.Add(2);
                //    int pair_val = 0;

                //    foreach (KeyValuePair<int, int> pair in dup_cards)
                //    {
                //        if (pair.Value == 2)
                //        {
                //            pair_val = pair.Key;
                //            Total.Add(pair.Key);
                //            break;
                //        }
                //    }

                //    for (int i = 0; i < desc_ordered_cards_fv.Count; i++)
                //    {
                //        if (desc_ordered_cards_fv[i] != pair_val)
                //        {
                //            Total.Add(desc_ordered_cards_fv[i]);
                //        }
                //    }
                //}
                //else if (isTwoPair())
                //{
                //    Total.Clear();
                //    Total.Add(3);
                //    List<int> pair_val = new List<int>();

                //    foreach (KeyValuePair<int, int> pair in dup_cards)
                //    {
                //        if (pair.Value == 2)
                //        {
                //            pair_val.Add(pair.Key);
                //        }
                //    }

                //    if (pair_val[0] > pair_val[1])
                //    {
                //        Total.Add(pair_val[0]);
                //        Total.Add(pair_val[1]);
                //    }
                //    else
                //    {
                //        Total.Add(pair_val[1]);
                //        Total.Add(pair_val[0]);
                //    }

                //    for (int i = 0; i < desc_ordered_cards_fv.Count; i++)
                //    {
                //        if (desc_ordered_cards_fv[i] != pair_val[0] || desc_ordered_cards_fv[i] != pair_val[1])
                //        {
                //            Total.Add(desc_ordered_cards_fv[i]);
                //        }
                //    }
                //}
                //else if (isThreeKind())
                //{
                //    Total.Clear();
                //    Total.Add(4);
                //    int trio_val = 0;

                //    foreach (KeyValuePair<int, int> pair in dup_cards)
                //    {
                //        if (pair.Value == 3)
                //        {
                //            trio_val = pair.Key;
                //            Total.Add(pair.Key);
                //            break;
                //        }
                //    }

                //    for (int i = 0; i < desc_ordered_cards_fv.Count; i++)
                //    {
                //        if (desc_ordered_cards_fv[i] != trio_val)
                //        {
                //            Total.Add(desc_ordered_cards_fv[i]);
                //        }
                //    }
                //}
                //else if (isStraight())
                //{
                //    Total.Clear();
                //    Total.Add(5);

                //    for (int i = 0; i < desc_ordered_cards_fv.Count; i++)
                //    {
                //        Total.Add(desc_ordered_cards_fv[i]);
                //    }
                //}
                //else if (isFlush())
                //{
                //    Total.Clear();
                //    Total.Add(6);

                //    for (int i = 0; i < desc_ordered_cards_fv.Count; i++)
                //    {
                //        Total.Add(desc_ordered_cards_fv[i]);
                //    }
                //}
                //else if (isFullHouse())
                //{
                //    Total.Clear();
                //    Total.Add(7);

                //    foreach (KeyValuePair<int, int> pair in dup_cards)
                //    {
                //        if (pair.Value == 3)
                //        {
                //            Total.Add(pair.Key);
                //            break;
                //        }
                //    }

                //    foreach (KeyValuePair<int, int> pair in dup_cards)
                //    {
                //        if (pair.Value == 2)
                //        {
                //            Total.Add(pair.Key);
                //            break;
                //        }
                //    }
                //}
                //else if (isFourKind())
                //{
                //    Total.Clear();
                //    Total.Add(8);

                //    foreach (KeyValuePair<int, int> pair in dup_cards)
                //    {
                //        if (pair.Value == 4)
                //        {
                //            Total.Add(pair.Key);
                //            break;
                //        }
                //    }
                //}
                //else if (isStraightFlush())
                //{
                //    Total.Clear();
                //    Total.Add(9);

                //    for (int i = 0; i < desc_ordered_cards_fv.Count; i++)
                //    {
                //        Total.Add(desc_ordered_cards_fv[i]);
                //    }
                //}
                //else if (isRoyalFlush())
                //{
                //    Total.Clear();
                //    Total.Add(10);

                //    for (int i = 0; i < desc_ordered_cards_fv.Count; i++)
                //    {
                //        Total.Add(desc_ordered_cards_fv[i]);
                //    }
                //}
                #endregion

                // Reverse
                if (isRoyalFlush())
                {
                    Total.Clear();
                    Total.Add(10);

                    for (int i = 0; i < desc_ordered_cards_fv.Count; i++)
                    {
                        Total.Add(desc_ordered_cards_fv[i]);
                    }
                }
                else if (isStraightFlush())
                {
                    Total.Clear();
                    Total.Add(9);

                    for (int i = 0; i < desc_ordered_cards_fv.Count; i++)
                    {
                        Total.Add(desc_ordered_cards_fv[i]);
                    }
                }
                else if (isFourKind())
                {
                    Total.Clear();
                    Total.Add(8);

                    foreach (KeyValuePair<int, int> pair in dup_cards)
                    {
                        if (pair.Value == 4)
                        {
                            Total.Add(pair.Key);
                            break;
                        }
                    }
                }
                else if (isFullHouse())
                {
                    Total.Clear();
                    Total.Add(7);

                    foreach (KeyValuePair<int, int> pair in dup_cards)
                    {
                        if (pair.Value == 3)
                        {
                            Total.Add(pair.Key);
                            break;
                        }
                    }

                    foreach (KeyValuePair<int, int> pair in dup_cards)
                    {
                        if (pair.Value == 2)
                        {
                            Total.Add(pair.Key);
                            break;
                        }
                    }
                }
                else if (isFlush())
                {
                    Total.Clear();
                    Total.Add(6);

                    for (int i = 0; i < desc_ordered_cards_fv.Count; i++)
                    {
                        Total.Add(desc_ordered_cards_fv[i]);
                    }
                }
                else if (isStraight())
                {
                    Total.Clear();
                    Total.Add(5);

                    for (int i = 0; i < desc_ordered_cards_fv.Count; i++)
                    {
                        Total.Add(desc_ordered_cards_fv[i]);
                    }
                }
                else if (isThreeKind())
                {
                    Total.Clear();
                    Total.Add(4);
                    int trio_val = 0;

                    foreach (KeyValuePair<int, int> pair in dup_cards)
                    {
                        if (pair.Value == 3)
                        {
                            trio_val = pair.Key;
                            Total.Add(pair.Key);
                            break;
                        }
                    }

                    for (int i = 0; i < desc_ordered_cards_fv.Count; i++)
                    {
                        if (desc_ordered_cards_fv[i] != trio_val)
                        {
                            Total.Add(desc_ordered_cards_fv[i]);
                        }
                    }
                }
                else if (isTwoPair())
                {
                    Total.Clear();
                    Total.Add(3);
                    List<int> pair_val = new List<int>();

                    foreach (KeyValuePair<int, int> pair in dup_cards)
                    {
                        if (pair.Value == 2)
                        {
                            pair_val.Add(pair.Key);
                        }
                    }

                    if (pair_val[0] > pair_val[1])
                    {
                        Total.Add(pair_val[0]);
                        Total.Add(pair_val[1]);
                    }
                    else
                    {
                        Total.Add(pair_val[1]);
                        Total.Add(pair_val[0]);
                    }

                    for (int i = 0; i < desc_ordered_cards_fv.Count; i++)
                    {
                        if (desc_ordered_cards_fv[i] != pair_val[0] || desc_ordered_cards_fv[i] != pair_val[1])
                        {
                            Total.Add(desc_ordered_cards_fv[i]);
                        }
                    }
                }
                else if (isPair())
                {
                    Total.Clear();
                    Total.Add(2);
                    int pair_val = 0;

                    foreach (KeyValuePair<int, int> pair in dup_cards)
                    {
                        if (pair.Value == 2)
                        {
                            pair_val = pair.Key;
                            Total.Add(pair.Key);
                            break;
                        }
                    }

                    for (int i = 0; i < desc_ordered_cards_fv.Count; i++)
                    {
                        if (desc_ordered_cards_fv[i] != pair_val)
                        {
                            Total.Add(desc_ordered_cards_fv[i]);
                        }
                    }
                }
                else if (isHighCard())
                {
                    Total.Clear();
                    Total.Add(1);

                    for (int i = 0; i < desc_ordered_cards_fv.Count; i++)
                    {
                        Total.Add(desc_ordered_cards_fv[i]);
                    }
                }
            }
        }

        public ObservableCollection<Card> CardsInPlay()
        {
            ObservableCollection<Card> cardsInPlay = new ObservableCollection<Card>();
            foreach (Card c in CardsOnHand)
            {
                if (c.FaceDown == true)
                {
                    c.ImageInUse = c.FDImage;
                }
                else
                {
                    c.ImageInUse = c.Image;
                }
                cardsInPlay.Add(c);
            }
            return cardsInPlay;
        }
    }
}
